<#
    .AUTHOR
        cw50406@imcnam.ssmb.com  
    .GROUP
        RPA AA STE Support Team(dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com)
    .VERSION
        2.0
    .Synopsis
        ControlRoom Service/Site/Pool Management
    .DESCRIPTION
        This script is used to start/stop/resart ControlRoom Service/Site/Pool,mainly in the weekend server reboot, also can be used daily
    .EXAMPLE
        .\CRManagement.ps1
        Run this script with all default parameters:
            $actionType="stop"
            $warning_mins=10
            $stop_mins=30
            $actionKind="all"
    .EXAMPLE
        .\CRManagement.ps1 start
        Start all the Service/Site/Pool
    .EXAMPLE
        .\CRManagement.ps1 start 5
        Start all the Service/Site/Pool with warning mins 5
    .Update
        09/20/2017--optimize code with more output comments in the script running process
        09/11/2017--optimize code with more clear comments structure
        08/29/2017--optimize email sending code with domain,env,node,running result ...
        08/17/2017--send notifications email to team
#>
param(
	[Parameter(Mandatory=$false)]
	[ValidateSet("start", "stop","restart")]         
	[string]$actionType="stop",                     # specify if this is to start/stop/restart in this script.
	[Parameter(Mandatory=$false)]               
	[int]$warning_mins=10,                      	# how many mins to wait before sending WARNING emails
	[Parameter(Mandatory=$false)]               
	[int]$stop_mins=30,                         	# how many mins to wait before continuing to try before fail
	[Parameter(Mandatory=$false)]                    
	[ValidateSet("all", "service","site","pool")]    
	[String]$actionKind="all"                       # specify which component to be started/stopped/restarted
)
Function Write-Log(){
	param(
		[Parameter(Mandatory=$true)]
		[ValidateSet("Warning", "Error", "Success","Normal")]
		[String]$logType,
		[Parameter(Mandatory=$true)]
		[String]$logInfo,
		[Parameter(Mandatory=$true)]
		[String]$logfile
	)
	(get-date).tostring("yyyy-MM-dd HH:mm:ss")+"--"+$logType+": "+$logInfo |Out-File -FilePath $logfile -Append -Encoding utf8 -Force
}
Function Check-AdminRight(){#---------------------Admin rights are required---------------------
	$cwi=[Security.Principal.WindowsIdentity]::GetCurrent()
	$cwp=[Security.Principal.WindowsPrincipal]$cwi
	if(!$cwp.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)){
		return $false
	}else{return $true}
}
Function Send-Mailtoteam( ){ # this function is used to send email to notify team that the script finished.
	param(
		[Parameter(Mandatory=$True)]    
		[string]$taskRunResult,         # the result og script running: SUCCESS, FAILED, WARNING
		[Parameter(Mandatory=$false)]    
		[string]$NotSuccessInfo         # the info in the subject to notify user what the not success info is
	)
	If( $actionType -ine "stop" ){
		$rebootmesseage="which has been last restarted at $last_reboot_time"
	}else{$rebootmesseage=$null}
	$jobType=(Get-Culture).TextInfo.ToTitleCase($actionType)
	$actionType= Switch ($actionType){
	    "start"{"started";break}
	    "stop"{"stopped";break}
        "restart"{"restarted"}
	}
	$this_pc=$env:computername
	$this_user=$env:username
	$domain=((Get-WmiObject Win32_ComputerSystem).Domain.Split(".")[0]).ToUpper()
	$node=Switch -regex ($this_pc.Substring($this_pc.Length-2)){
	    "01|49|E2|9a"   {"1";break}
	    "02|b8|0e|ae"   {"2"}
	}
	$env=Switch -regex ($this_pc.Substring(7,3).ToLower()){ # check computer name to tell the env
	    "p2n"           {"PROD";break}
	    "u2n"           {"UAT";break}
	    "-f2|-18|-aa"   {"DEV";break}
	    "-44|-97|-c2"   {"POC";break}
	    "-f3|-3d"       {"LAB";break}
	    "c2n"           {"COB";break}
	    "e2n"           {"PTE";break}
	    default         {$this_pc}
	}
	$env="[$env-$domain-$node]"
	Switch ($taskRunResult){
	    "SUCCESS"{$body_message="been $actionType";break}
	    default{$body_message="encountered an error when starting";break}
	}
	Try{ # cw50406@imcnam.ssmb.com  dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com
		Send-MailMessage `
            -From ($env:username +"."+$this_pc+"@imcnam.ssmb.com") `
            -To dl.gt.cn.cstc.rpa.aa.ste@imcnam.ssmb.com `
            -Subject "$env RPA AA STE WeekendCRManagement $jobType - $taskRunResult$NotSuccessInfo" `
            -Body "Hi RPA AA STE Support, `n`nWeekendCRManagement has $body_message in $this_pc $rebootmesseage.`n`nPlease check details in the attached log. `n`nThank You! `n`n$this_user" `
            -Attachments $logfile `
            -SmtpServer "imta.citicorp.com" -Port 25 `
            -Encoding([System.Text.Encoding]::UTF8) -ea 1
       Write-Log Success 'The notify email has been sent to RPA AA STE team.' $logfile
	}Catch{
	    Write-Log Error $_ $logfile
	}Finally{}
}
Function Export-LogToAutosys($logfile){ # this function is used to write log to autosys log file
		Switch($actionType){ # check $actionType to tell which autosys log file to add log
		"start"{$logname="start_out"}
		"stop"{$logname="stop_out"}
		"restart"{$logname="restart_out"}
	}
	$autosysLog = "C:\Program Files\CA\Workload Automation AE\SystemAgent\WA1_AGENT\log\WeekendCRManagement"
	If(!(test-path $autosysLog)){new-item -ItemType Directory -Path $autosysLog -force 1>$null}
	$autosysLog="$autosysLog\$logname.log"
	If(!(test-path $autosysLog)){new-item -ItemType File -Path $autosysLog -force 1>$null}
	Write-Log Normal "----------------------------END OF SCRIPT----------------------------`n" $logfile
	Try{
		get-content $logfile -ea 1|Add-Content $autosysLog -Force -Encoding UTF8 -ea 1
	}Catch{
	    write-log Error $_ $logfile
	}Finally{}
}
Function Set-ComponentTo($actionType,$item){
	Switch -regex ($item){ # setup run cmdlets based on given item
		"^(World|Windows)|Cache Manager$"{$cmdlets1="(Get-Service '$item').status";$cmdlets2="Start-Service '$item'";$cmdlets3="Stop-Service '$item'";$info="$item Service";break}
		"^Automation Anywhere$"{$cmdlets1="(Get-WebSiteState '$item').value";$cmdlets2="Start-WebSite '$item'";$cmdlets3="Stop-WebSite '$item'";$info="$item Site";break}
		"(Pool|Scheduler)$"{$cmdlets1="(Get-WebAppPoolState '$item').value";$cmdlets2="start-WebAppPool '$item'";$cmdlets3="Stop-WebAppPool '$item'";$info="$item Pool";break}
	}
	$run_mins=((get-date) -$start_time).totalminutes 
	If( $run_mins -gt $stop_mins){ # exit if running time is greater than $stop_mins
		Write-Log Error "Unable to $actionType '$info' in $stop_mins mins" $logfile
		$actionType=(Get-Culture).TextInfo.ToTitleCase($actionType)
		Export-LogToAutosys $logfile ; Send-Mailtoteam FAILED ": $info Not $actionType"
		exit
	}elseif(!$script:mail_sent){  # sending warning emails
		If( $run_mins -gt $warning_mins ){
		    $script:mail_sent=$true
			Write-Log Error "Unable to $actionType '$info' in $warning_mins mins" $logfile
			Send-Mailtoteam WARNING ": Maximum run time reached"
		}
	}
	Try{
        If(!$script:logwrite){Write-Log Normal "Checking status of '$info' ..." $logfile}
		$status=iex $cmdlets1 -ErrorAction Stop
		If($actionType -ieq "Start"){
			If($status -inotmatch "Running|Started"){
                If(!$script:logwrite){Write-Log Normal "Trying to $actionType '$info'" $logfile ; $script:logwrite=$true}
                Try{        iex $cmdlets2 -ErrorAction Stop
                }Catch{     Write-Log Error $_ $logfile
                }Finally{   sleep 10 ; Set-ComponentTo $actionType $item}
			}else{
                If( $script:logwrite ){ $str='now'}else{$str='already'}
                Write-Log Success "'$info' is $str in Started status." $logfile ; $script:logwrite=$false ; $start_time=get-date; return $true
            }
		}elseIf($actionType -ieq "Stop"){
			If($status -imatch "Running|Started"){
                If(!$script:logwrite){Write-Log Normal "Trying to $actionType '$info'" $logfile ; $script:logwrite=$true}
                Try{        iex $cmdlets3 -ErrorAction Stop
                }Catch{     Write-Log Error $_ $logfile
                }Finally{   sleep 10 ; Set-ComponentTo $actionType $item}
			}else{
                If( $script:logwrite ){ $str='now'}else{$str='already'}
                Write-Log Success "'$info' is $str in Stopped status." $logfile ; $script:logwrite=$false ; $start_time=get-date; return $true
            }
		}
	}Catch{
		Write-Log Error $_ $logfile ; $script:logwrite=$true ; sleep 10;Set-ComponentTo $actionType $item
	}Finally{}
}
$thisPath = Split-Path -Parent ($MyInvocation.MyCommand.Definition) ; $logPath = $thisPath.Replace('\scripts\','\logs\')
If(!(test-path $logPath)){ new-item -ItemType Directory -Path $logPath -force 1>$null }
$logfile="$logPath\$((get-date).tostring('yyyyMMdd_HHmmss'))_WeekendCRManagement_$actionKind_$actionType.log"
Write-Log Normal "----------------------------START OF SCRIPT----------------------------" $logfile
If( ! (Check-AdminRight) ){
    Write-Log Error "This script needs admin access to run while the current user $($env:username) is either not in admin group or not run this script as admin!" $logfile
    Write-Log Normal "----------------------------END OF SCRIPT----------------------------" $logfile
    Send-Mailtoteam FAILED ": Access Denied"
    exit
}
$last_reboot_time=(Get-CimInstance -ClassName win32_operatingsystem).lastbootuptime.ToString("MM/dd/yyyy HH:mm:ss")
If( $actionType -ieq "start" ){
	Write-Log Normal "This VM server has been last restarted at $last_reboot_time" $logfile
}
$start_time=get-date ; $script:mail_sent=$false ; $script:logwrite=$false
#<---------------------------------------------------------------------intilize variables
Set-Variable AACM -option Constant -value "Automation Anywhere Cache Manager" ; Set-Variable AA -option Constant -value "Automation Anywhere"
Set-Variable AAAP -option Constant -value "AutomationAnywhereAppPool" ; Set-Variable AAS -option Constant -value "AutomationAnywhereScheduler"
Set-Variable W3PS -option Constant -value "World Wide Web Publishing Service" ; Set-Variable WPAS -option Constant -value "Windows Process Activation Service"
Write-Log Normal "Trying to $actionType ControlRoom Setup-$($actionKind.ToUpper()).." $logfile
If($actionType -eq "restart" ){ # take relevent actions If this is for restart
	If($actionKind -eq "all"){ # take relevent actions for all steps
		If( Set-ComponentTo Stop $W3PS ){ # stop World Wide Web Publishing Service
			If(Set-ComponentTo Stop $AACM){ # stop Automation Anywhere Cache Manager service
				If(Set-ComponentTo Stop $AA){ # stop Automation Anywhere site
					If(Set-ComponentTo Stop $AAAP){ # stop Automation Anywhere App Pool
						If(Set-ComponentTo Stop $AAS){ # stop AutomationAnywhereScheduler Pool
							Set-ComponentTo Start $W3PS 1>$null # start World Wide Web Publishing Service
						}
						Set-ComponentTo Start $AACM 1>$null # start Automation Anywhere Cache Manager service
					}
					Set-ComponentTo Start $AA 1>$null # start Automation Anywhere site
				}
				Set-ComponentTo Start $AAAP 1>$null # start Automation Anywhere App Pool
			}
		    Set-ComponentTo Start $AAS 1>$null  # start AutomationAnywhereScheduler Pool
		}
	}else{
		Switch($actionKind){ # take relevent actions for seperated step
		    "service"{If(Set-ComponentTo Stop $AACM){Set-ComponentTo Start $AACM 1>$null}}
		    "site"{If(Set-ComponentTo Stop $AA){Set-ComponentTo Start $AA 1>$null}}
		    "pool"{If(Set-ComponentTo Stop $AAAP){Set-ComponentTo Start $AAAP 1>$null};If(Set-ComponentTo Stop $AAS){Set-ComponentTo Start $AAS 1>$null}}
		}
	}
	Set-ComponentTo Start $WPAS 1>$null
}else{ # take relevent actions If this is for start/stop
	If($actionKind -eq "all"){ # take relevent actions for all steps
		Set-ComponentTo $actionType $AACM 1>$null; Set-ComponentTo $actionType $AA 1>$null
		Set-ComponentTo $actionType $AAAP 1>$null; Set-ComponentTo $actionType $AAS 1>$null
	}else{
		Switch($actionKind){ # take relevent actions for seperated step
			"service"{Set-ComponentTo $actionType $AACM 1>$null}
			"site"{Set-ComponentTo $actionType $AA 1>$null}
			"pool"{Set-ComponentTo $actionType $AAAP 1>$null; Set-ComponentTo $actionType $AA 1>$null}
		}
	}
	If( $actionType -ne "stop" ){ # restart World Wide Web Publishing Service and "Windows Process Activation Service"
		Set-ComponentTo Stop $W3PS 1>$null ; Set-ComponentTo Start $W3PS 1>$null ; 	Set-ComponentTo Start $WPAS 1>$null
	}
}
#<---------------------------------- add powershell log to autosys log and send the email
Export-LogToAutosys $logfile ; Send-Mailtoteam SUCCESS